package com.uduemc.biso.node.web.api.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysLanguage;
import com.uduemc.biso.core.extities.node.custom.LoginNode;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RedisUtil;
import com.uduemc.biso.node.core.common.entities.ThemeObject;
import com.uduemc.biso.node.core.common.siteconfig.SiteMenuConfig;
import com.uduemc.biso.node.core.common.themepojo.ThemeColor;
import com.uduemc.biso.node.core.entities.HDomain;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.entities.SPage;
import com.uduemc.biso.node.core.entities.custom.CustomThemeColor;
import com.uduemc.biso.node.core.node.config.OperateLoggerStaticModel;
import com.uduemc.biso.node.core.node.config.OperateLoggerStaticModelAction;
import com.uduemc.biso.node.core.operate.entities.OperateLog;
import com.uduemc.biso.node.core.utils.FilterResponse;
import com.uduemc.biso.node.web.api.component.CopySiteAsync;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.pojo.SiteBaseInfo;
import com.uduemc.biso.node.web.api.service.DomainService;
import com.uduemc.biso.node.web.api.service.HostSetupService;
import com.uduemc.biso.node.web.api.service.LanguageService;
import com.uduemc.biso.node.web.api.service.PageService;
import com.uduemc.biso.node.web.api.service.SConfigService;
import com.uduemc.biso.node.web.api.service.SiteService;
import com.uduemc.biso.node.web.api.service.ThemeService;
import com.uduemc.biso.node.web.api.service.WebSiteService;
import com.uduemc.biso.node.web.api.service.impl.CenterServiceImpl;
import com.uduemc.biso.node.web.component.operate.OperateLoggerController;
import com.uduemc.biso.node.web.service.OperateLoggerService;

import cn.hutool.core.collection.CollUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("/api/site")
@Api(tags = "Site模块")
public class SiteController {
	private final Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private SConfigService sConfigServiceImpl;

	@Autowired
	private SiteService siteServiceImpl;

	@Autowired
	private CenterServiceImpl centerServiceImpl;

	@Autowired
	private ThemeService themeServiceImpl;

	@Autowired
	private WebSiteService webSiteServiceImpl;

	@Autowired
	private DomainService domainServiceImpl;

	@Autowired
	private CopySiteAsync copySiteAsync;

	@Autowired
	private RedisUtil redisUtil;

	@Autowired
	private OperateLoggerService operateLoggerServiceImpl;

	@Autowired
	private LanguageService languageServiceImpl;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private HostSetupService hostSetupServiceImpl;

	@Autowired
	private PageService pageServiceImpl;

	@PostMapping("/info")
	public JsonResult site(HttpServletRequest request) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		// 获取默认站点
		Site site = requestHolder.getCurrentSite();
		// 默认站点的配置信息
		SConfig sConfig = sConfigServiceImpl.getInfoBySiteId(site.getId());
		// 获取整个站点列表
		List<Site> siteList = siteServiceImpl.getSiteList();
		// 所有的语言信息
		List<SysLanguage> allLanguage = centerServiceImpl.getAllLanguage();

		HDomain defaultDomain = domainServiceImpl.getDefaultDomain();

		List<SPage> listSPage = pageServiceImpl.getInfosByHostSiteId();

		Map<String, Object> result = new HashMap<>();
		result.put("host", requestHolder.getHost());
		result.put("site", site);
		result.put("init", CollUtil.isNotEmpty(listSPage) ? 1 : 0);
		result.put("sConfig", sConfig);
		result.put("siteList", siteList);
		result.put("allLanguage", allLanguage);
		result.put("defaultdomain", defaultDomain);
		result.put("loginDomain", requestHolder.getCurrentLoginNode().getLoginDomain());
		result.put("loginUrl", requestHolder.getCurrentLoginNode().getLoginUrl());
		return JsonResult.ok(result);
	}

	/**
	 * 修改编辑当前的站点
	 * 
	 * @param siteId
	 * @return
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws JsonProcessingException
	 * @throws IOException
	 */
	@PostMapping("/change")
	public JsonResult change(@RequestParam("siteId") String siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		// 通过 获取欢迎页的基础信息
		logger.info("defaultSiteId: " + requestHolder.getCurrentSite().getId());
		logger.info("siteId: " + siteId);
		long changeSiteId = 0;
		try {
			changeSiteId = Long.valueOf(siteId);
		} catch (NumberFormatException e) {
		}
		if (changeSiteId < 1 || changeSiteId == requestHolder.getCurrentSite().getId().longValue()) {
			return JsonResult.illegal();
		}
		// 是否存在
		Site changeSite = null;
		List<Site> sites = requestHolder.getSites();
		for (Site site : sites) {
			if (site.getId().longValue() == changeSiteId) {
				changeSite = site;
				break;
			}
		}
		if (changeSite == null) {
			return JsonResult.illegal();
		}
		LoginNode loginNode = requestHolder.getCurrentLoginNode();
		loginNode.setCurrentSiteId(changeSite.getId());

		String redisKey = loginNode.getRedisKey();
		if (redisUtil.set(redisKey, loginNode, 3600L * 4) == false) {
			return JsonResult.assistance();
		}

		return JsonResult.ok(1);
	}

	/**
	 * 修改站点的状态
	 * 
	 * @param sconfigid
	 * @return
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws JsonProcessingException
	 * @throws IOException
	 */
	@PostMapping("/change/sitestatus")
	public JsonResult changeSiteStatus(@RequestParam("sconfigid") Long sconfigid)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (sconfigid == null || sconfigid.longValue() < 0L) {
			return JsonResult.illegal();
		}

		// 修改SConfig的status
		JsonResult jsonResult = sConfigServiceImpl.changeStatus(sconfigid);
		if (jsonResult != null) {
			// 失败
			return jsonResult;
		}

		// 清理页面内容缓存
		webSiteServiceImpl.cacheCurrentHostClear();

		SiteBaseInfo siteBaseInfo = siteServiceImpl.getSiteBaseInfoOnlyLanguages();
		return JsonResult.ok(siteBaseInfo);
	}

	@PostMapping("/baseinfo")
	public JsonResult baseinfo() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SiteBaseInfo siteBaseInfo = siteServiceImpl.getSiteBaseInfo();
		return JsonResult.ok(siteBaseInfo);
	}

	/**
	 * 获取所有的站点列表数据
	 * 
	 * @return
	 * @throws IOException
	 * @throws JsonProcessingException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	@PostMapping("/site-config-status-infos")
	public JsonResult siteInfos() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<SConfig> listSConfig = sConfigServiceImpl.getCurrentInfosByHostId();
		return JsonResult.ok(listSConfig);
	}

	/**
	 * 获取改变默认站点
	 * 
	 * @return
	 * @throws IOException
	 * @throws JsonProcessingException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	@PostMapping("/change-default-site-and-infos")
	public JsonResult changeDefaultSiteAndInfos(@RequestParam("defaultSiteId") long defaultSiteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		boolean bool = sConfigServiceImpl.changeDefaultSiteAndInfos(defaultSiteId);
		if (!bool) {
			return JsonResult.assistance();
		}
		List<SConfig> listSConfig = sConfigServiceImpl.getCurrentInfosByHostId();
		webSiteServiceImpl.cacheCurrentHostClear();
		return JsonResult.messageSuccess("修改成功！", listSConfig);
	}

	/**
	 * 获取当前站点的菜单配置
	 */
	@PostMapping("/get-site-menu-config")
	public JsonResult getSiteMenuConfig() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SiteMenuConfig siteMenuConfig = sConfigServiceImpl.getCurrentSiteMenuConfig();
		if (siteMenuConfig == null) {
			return JsonResult.assistance();
		}
		return JsonResult.ok(siteMenuConfig);
	}

	/**
	 * 获取当前站点下的颜色列表以及，当前站点的主题颜色
	 * 
	 * @return
	 * @throws IOException
	 * @throws JsonProcessingException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 */
	@PostMapping("/get-current-theme-color")
	public JsonResult getCurrentThemeColor() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SConfig sConfig = sConfigServiceImpl.getCurrentInfo();
		String theme = sConfig.getTheme();
		String color = sConfig.getColor();
		ThemeColor themeColorByTheme = themeServiceImpl.getThemeColorByTheme(theme);
		CustomThemeColor customThemeColor = sConfigServiceImpl.getCustomThemeColor(sConfig);
		Map<String, Object> result = new HashMap<>();
		result.put("theme", theme);
		result.put("color", color);
		result.put("themeColor", themeColorByTheme);
		result.put("customThemeColor", customThemeColor);
		return JsonResult.ok(result);
	}

	/**
	 * 通过传入的参数 color 修改当前站点的主题颜色
	 * 
	 * @param color
	 * @return
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws JsonProcessingException
	 * @throws IOException
	 */
	@ApiOperation(value = "修改主题颜色", notes = "通过 color、customThemeColor 修改主题颜色，支持自定义主题颜色")
	@ApiImplicitParams({ @ApiImplicitParam(name = "color", value = "修改主题颜色，如果是自定义主题颜色， color 为 custom", required = true),
			@ApiImplicitParam(name = "customThemeColor", value = "自定义主题颜色的配置项，字符串数据类型，数据结构同 /get-current-theme-color 接口获取的 customThemeColor 数据字段", required = true) })
	@PostMapping("/update-site-theme-color")
	public JsonResult updateSiteThemeColor(@RequestParam("color") String color, @RequestParam("customThemeColor") String customThemeColor)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SConfig sConfig = sConfigServiceImpl.getCurrentInfo();
		sConfig.setColor(color).setCustomThemeColorConfig(customThemeColor);
		SConfig updateAllSiteConfig = sConfigServiceImpl.updateAllSiteConfig(sConfig);
		if (updateAllSiteConfig == null) {
			return JsonResult.illegal();
		}
		webSiteServiceImpl.cacheCurrentSiteClear();
		return JsonResult.messageSuccess("修改成功！", updateAllSiteConfig);
	}

	/**
	 * 获取目前次控端所拥有的主题，同时获取当前站点所使用的主题
	 * 
	 * @return
	 * @throws IOException
	 */
	@PostMapping("/site-theme-current")
	public JsonResult siteThemeCurrent() throws IOException {
		List<ThemeObject> allPackageObject = themeServiceImpl.getAllThemeObject();
		FilterResponse.filterPackageObjectInfo(allPackageObject);
		SConfig sConfig = sConfigServiceImpl.getCurrentInfo();
		String theme = sConfig.getTheme();
		Map<String, Object> result = new HashMap<>();
		result.put("allTheme", allPackageObject);
		result.put("current", theme);
		return JsonResult.ok(result);
	}

	/**
	 * 修改当前站点的主题
	 * 
	 * @return
	 * @throws IOException
	 */
	@PostMapping("/update-site-theme")
	public JsonResult updateSiteTheme(@RequestParam("theme") String theme) throws IOException {
		boolean bool = false;
		List<ThemeObject> allThemeObject = themeServiceImpl.getAllThemeObject();
		if (CollectionUtils.isEmpty(allThemeObject)) {
			return JsonResult.illegal();
		}
		for (ThemeObject themeObject : allThemeObject) {
			if (themeObject.getId().equals(theme)) {
				bool = true;
				break;
			}
		}
		if (!bool) {
			return JsonResult.illegal();
		}
		SConfig sConfig = sConfigServiceImpl.getCurrentInfo();
		if (sConfig.getTheme().equals(theme)) {
			return JsonResult.messageSuccess("修改主题成功！", theme);
		}
		sConfig.setTheme(theme).setColor("0");
		SConfig update = sConfigServiceImpl.updateAllSiteConfig(sConfig);
		if (update == null) {
			return JsonResult.assistance();
		}
		webSiteServiceImpl.cacheCurrentSiteClear();
		return JsonResult.messageSuccess("修改主题成功！", theme);
	}

	/**
	 * 获取目前次控端当前站点的 s_config 中的 status
	 * 
	 * @return
	 * @throws IOException
	 */
	@PostMapping("/site-config-status")
	public JsonResult siteConfigStatus() throws IOException {
		SConfig sConfig = sConfigServiceImpl.getCurrentInfo();
		return JsonResult.ok(sConfig.getStatus());
	}

	/**
	 * 获取目前次控端当前站点的 s_config 中的 status
	 * 
	 * @return
	 * @throws IOException
	 * @throws JsonProcessingException
	 * @throws JsonMappingException
	 * @throws JsonParseException
	 * @throws Exception
	 */
	@ApiOperation(value = "站点语言复制", notes = "通过参数中的 toSiteId 为复制到的站点数据ID")
	@ApiImplicitParams({ @ApiImplicitParam(name = "toSiteId", value = "复制的到站点 site 数据 ID", required = true) })
	@PostMapping("/copy")
	public JsonResult copy(@RequestParam("toSiteId") long toSiteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		Host host = requestHolder.getHost();
		Site currentSite = requestHolder.getCurrentSite();
		long fromSiteId = currentSite.getId().longValue();

		List<Site> sites = requestHolder.getSites();
		Site fromSite = null;
		Site toSite = null;
		for (Site site : sites) {
			if (fromSite == null && site.getId().longValue() == fromSiteId) {
				fromSite = site;
			}
			if (toSite == null && site.getId().longValue() == toSiteId) {
				toSite = site;
			}
		}

		if (fromSite != null && toSite != null) {

			SysLanguage fromLanguage = languageServiceImpl.getLanguageBySite(fromSite);
			SysLanguage toLanguage = languageServiceImpl.getLanguageBySite(toSite);

			if (fromSiteId == toSiteId) {
				return JsonResult.messageError(fromLanguage.getName() + " 不能被复制到 " + toLanguage.getName());
			}

			// 判断站点页面数量
			int fromSiteUsedPage = hostSetupServiceImpl.getSiteUsedPage(fromSiteId);
			int toSiteUsedPage = hostSetupServiceImpl.getSiteUsedPage(toSiteId);
			int subUsedPage = fromSiteUsedPage - toSiteUsedPage;
			if (subUsedPage > 0) {
				int page = hostSetupServiceImpl.getPage();
				int usedPage = hostSetupServiceImpl.getUsedPage();
				if ((usedPage + subUsedPage) > page) {
					return JsonResult.messageError("当前页面数不够，还需要" + subUsedPage + "个页面");
				}
			}

			// 判断站点系统数量
			int fromSiteUsedSysmte = hostSetupServiceImpl.getSiteUsedSysmte(fromSiteId);
			int toSiteUsedSysmte = hostSetupServiceImpl.getSiteUsedSysmte(toSiteId);
			int subUsedSysmte = fromSiteUsedSysmte - toSiteUsedSysmte;
			if (subUsedSysmte > 0) {
				int system = hostSetupServiceImpl.getSystem();
				int usedSysmte = hostSetupServiceImpl.getUsedSysmte();
				if ((usedSysmte + subUsedSysmte) > system) {
					return JsonResult.messageError("当前系统数不够，还需要" + subUsedSysmte + "个系统");
				}
			}

			// 判断系统表单数量
			int fromSiteUsedForm = hostSetupServiceImpl.getSiteUsedForm(fromSiteId);
			int toSiteUsedForm = hostSetupServiceImpl.getSiteUsedForm(toSiteId);
			int subUsedForm = fromSiteUsedForm - toSiteUsedForm;
			if (subUsedForm > 0) {
				int form = hostSetupServiceImpl.getForm();
				int usedForm = hostSetupServiceImpl.getUsedForm();
				if ((usedForm + subUsedForm) > form) {
					return JsonResult.messageError("当前表单数不够，还需要" + subUsedForm + "个表单");
				}
			}

			// 写入正在执行的日志
			Map<String, Object> param = new HashMap<>();
			param.put("fromSiteId", fromSiteId);
			param.put("toSiteId", toSiteId);
			OperateLog insert = initLog(fromLanguage.getName(), toLanguage.getName(), objectMapper.writeValueAsString(param));
			if (insert == null) {
				return JsonResult.assistance();
			}

			copySiteAsync.copy(host.getId(), fromSiteId, toSiteId, insert);
			return JsonResult.messageSuccess("站点（" + toLanguage.getName() + "）复制中！");
		}
		return JsonResult.illegal();
	}

	protected OperateLog initLog(String fromLanText, String toLanText, String param)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		String declaringTypeName = "com.uduemc.biso.node.web.api.controller.SiteController";
		String modelName = OperateLoggerStaticModel.findModelName(declaringTypeName);
		String modelAction = OperateLoggerStaticModel.findModelAction(declaringTypeName, OperateLoggerStaticModelAction.COPY_SITE);
		String content = "站点 " + fromLanText + " 复制到 " + toLanText;
		short status = 2;

		Long hostId = requestHolder.getHost().getId();
		Long siteId = requestHolder.getCurrentSite().getId();
		Integer languageId = requestHolder.getCurrentSite().getLanguageId();
		LoginNode loginNode = requestHolder.getCurrentLoginNode();
		Long loginUserId = loginNode.getLoginUserId();
		String loginUserType = loginNode.getLoginUserType();
		String loginUserName = loginNode.getLoginUserName();
		String ipAddress = OperateLoggerController.ipAddress(requestHolder.getCurrentRequest());

		OperateLog operateLog = new OperateLog();
		operateLog.setHostId(hostId).setSiteId(siteId).setLanguageId(languageId).setUserId(loginUserId).setUserType(loginUserType).setUsername(loginUserName)
				.setModelName(modelName).setModelAction(modelAction).setContent(content).setParam(param).setReturnValue("").setOperateItem("").setStatus(status)
				.setIpaddress(ipAddress);

		OperateLog insert = operateLoggerServiceImpl.insert(operateLog);
		return insert;
	}

	@PostMapping("/search-page-config")
	@ApiOperation(value = "全站搜索页面中配置", notes = "获取全站搜索页面中内容配置")
	public JsonResult searchPageConfig() throws IOException {
		return sConfigServiceImpl.searchPageConfig();
	}

	@PostMapping("/update-search-page-config")
	@ApiOperation(value = "修改全站搜索页面中配置", notes = "修改全站搜索页面中配置，返回写入成功后的配置，同 /search-page-config")
	public JsonResult updateSearchPageConfig(@RequestParam("searchPageConfigString") String searchPageConfigString) throws IOException {
		return sConfigServiceImpl.updateSearchPageConfig(searchPageConfigString);
	}

}
